package com.tools.common.object.type;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.tools.common.container.AbsOwnList;
import com.tools.common.container.OwnPairs;
import com.tools.common.container.OwnRows;
import com.tools.common.object.C;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;
import com.tools.common.object.json.JsonKit;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 类型处理公共方法
 * */
@Note("类型处理公共方法")
public final class CTKit {

    private CTKit() {}


    @Note("处理 map 中 key 的类型")
    public static Object handleKeyOfMap(Object key, C<?> keyType, Class<?> containerType) {
        if(keyType == null) return key;
        if(String.class.equals(keyType.getMainType())) {
            if(ConcurrentHashMap.class.equals(containerType)) {
                return ObjKit.toStringValue(key, "null", false);
            }
            return ObjKit.toStringValue(key, null, false);
        }
        return ObjKit.toRealValue(key, keyType);
    }


    @Note("将 sourceMap 的值全部拷贝到 targetMap 中")
    public static void mapToMapFillIn(Map sourceMap, Map targetMap, C<?> targetType) {
        Class<?> targetClass = targetType.getMainType();
        if(targetType.hasGenericType()) {
            C<?> keyType = targetType.generic(0);
            C<?> valueType = targetType.generic(1);
            for (Object o : sourceMap.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                Object realKey = CTKit.handleKeyOfMap(e.getKey(), keyType, targetClass);
                Object realValue = ObjKit.toRealValue(e.getValue(), valueType);
                targetMap.put(realKey, realValue);
            }
            return;
        }
        targetMap.putAll(sourceMap);
    }


    @Note("将 sourcePairs 的值全部拷贝到 targetMap 中")
    public static void pairsToMapFillIn(OwnPairs sourcePairs, Map targetMap, C<?> targetType) {
        Class<?> targetClass = targetType.getMainType();
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(1);
            C<?> keyType = targetType.generic(0);
            for (Object o : sourcePairs.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                Object realValue = ObjKit.toRealValue(e.getValue(), valueType);
                Object realKey = CTKit.handleKeyOfMap(e.getKey(), keyType, targetClass);
                targetMap.put(realKey, realValue);
            }
            return;
        }
        for (Object o : sourcePairs.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            targetMap.put(e.getKey(), e.getValue());
        }
    }


    @Note("将 sourceMap 的值全部拷贝到 targetPairs 中")
    public static void mapToOwnPairsFillIn(Map sourceMap, OwnPairs targetPairs, C<?> targetType) {
        Class<?> targetClass = targetType.getMainType();
        if(targetType.hasGenericType()) {
            C<?> keyType = targetType.generic(0);
            C<?> valueType = targetType.generic(1);
            for (Object o : sourceMap.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                Object realKey = CTKit.handleKeyOfMap(e.getKey(), keyType, targetClass);
                targetPairs.put(realKey, ObjKit.toRealValue(e.getValue(), valueType));
            }
            return;
        }
        targetPairs.putAll(sourceMap);
    }


    @Note("将 sourcePairs 的值全部拷贝到 targetPairs 中")
    public static void pairsToOwnPairsFillIn(OwnPairs sourcePairs, OwnPairs targetPairs, C<?> targetType) {
        Class<?> targetClass = targetType.getMainType();
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(1);
            C<?> keyType = targetType.generic(0);
            for (Object o : sourcePairs.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                Object realKey = CTKit.handleKeyOfMap(e.getKey(), keyType, targetClass);
                targetPairs.put(realKey, ObjKit.toRealValue(e.getValue(), valueType));
            }
            return;
        }
        targetPairs.putAll(sourcePairs);
    }


    @Note("简单地将 Iterable 的内容拷贝到目标 Collection 里")
    public static void iterableToCollection(Iterable src, Collection target) {
        for (Object o : src) {
            target.add(o);
        }
    }

    @Note("将 Iterable 的内容经过类型的转换后，拷贝到目标 Collection 里")
    public static void iterableToCollectionFillIn(Iterable src, Collection target, C<?> targetType) {
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(0);
            for (Object o : src) {
                Object realValue = ObjKit.toRealValue(o, valueType);
                target.add(realValue);
            }
            return;
        }
        iterableToCollection(src, target);
    }


    @Note("将数组里的内容经过类型的转换后，拷贝到目标 Collection 里")
    public static void arrayToCollectionFillIn(Object[] src, Collection target, C<?> targetType) {
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(0);
            for (Object o : src) {
                Object realValue = ObjKit.toRealValue(o, valueType);
                target.add(realValue);
            }
            return;
        }
        Collections.addAll(target, src);
    }


    @Note("将 Iterable 的内容经过类型的转换后，拷贝到目标 OwnRows 里")
    public static void iterableToOwnRowsFillIn(Iterable src, OwnRows target, C<?> targetType) {
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(0);
            for (Object o : src) {
                target.add(ObjKit.toRealValue(o, valueType));
            }
            return;
        }
        target.addAll(src);
    }


    @Note("将数组里的内容经过类型的转换后，拷贝到目标 OwnRows 里")
    public static void arrayToOwnRowsFillIn(Object[] src, OwnRows target, C<?> targetType) {
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(0);
            for (Object o : src) {
                target.add(ObjKit.toRealValue(o, valueType));
            }
            return;
        }
        target.addAll(src);
    }


    @Note("私有逻辑：将 JsonParser 转为 Collection 集合的具体逻辑")
    public static Collection addJsonDataInCollection(JsonParser parser, Collection set, C<?> targetType) throws IOException {
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(0);
            while (parser.nextToken() != JsonToken.END_ARRAY) {
                Object value = JsonKit.parseToken(parser, valueType);
                Object realValue = ObjKit.toRealValue(value, valueType);
                set.add(realValue);
            }
            return set;
        }
        while (parser.nextToken() != JsonToken.END_ARRAY) {
            Object value = JsonKit.parseToken(parser);
            set.add(value);
        }
        return set;
    }



    @Note("私有逻辑：将 JsonParser 转为 OwnRows 集合的具体逻辑")
    public static OwnRows addJsonDataInOwnRows(JsonParser parser, OwnRows rows, C<?> targetType) throws IOException {
        if(targetType.hasGenericType()) {
            C<?> valueType = targetType.generic(0);
            while (parser.nextToken() != JsonToken.END_ARRAY) {
                Object value = JsonKit.parseToken(parser, valueType);
                rows.add(ObjKit.toRealValue(value, valueType));
            }
            return rows;
        }
        while (parser.nextToken() != JsonToken.END_ARRAY) {
            Object value = JsonKit.parseToken(parser);
            rows.add(value);
        }
        return rows;
    }

}
